package com.example.common.config;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.example.common.Constants;
import com.example.common.enums.ErrorCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.exception.CustomException;
import com.example.pojo.entity.Account;
import com.example.pojo.entity.Admin;
import com.example.pojo.entity.PetShop;
import com.example.pojo.entity.User;
import com.example.service.AdminService;
import com.example.service.PetShopService;
import com.example.service.UserService;
import com.example.utils.AccountUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * JWT 拦截器
 */
@Component
public class JWTInterceptor implements HandlerInterceptor {

    @Resource
    private UserService userService;

    @Resource
    private PetShopService petShopService;

    @Resource
    private AdminService adminService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 1.从请求头中拿到 token
        String token = request.getHeader(Constants.TOKEN);
        // 2.如果从请求头没拿到，那么从请求参数里拿
        if (StrUtil.isBlank(token)) {
            token = request.getParameter(Constants.TOKEN);
        }
        // 3.校验请求头是否带了 token
        if (StrUtil.isBlank(token)) {
            throw new CustomException(ErrorCodeEnum.TOKEN_INVALID_ERROR);
        }
        Account account = null;
        int id;
        String role;
        try {
            // 4.解析 JWT，拿出内容
            String audience = JWT.decode(token).getAudience().get(0);
            // 5.拿出账号id和角色，JWT内容为：账号id-角色，如 23-ADMIN
            id = Integer.parseInt(audience.split("-")[0]);
            role = audience.split("-")[1];
        } catch (Exception e) {
            throw new CustomException(ErrorCodeEnum.TOKEN_CHECK_ERROR);
        }
        // 6.根据角色和账户id查询账户
        if (RoleEnum.USER.name().equals(role)) {
            // 6.1 查询普通用户账户
            account = this.userService.lambdaQuery()
                    .eq(User::getId, id)
                    .one();
        } else if (RoleEnum.PETSHOP.name().equals(role)) {
            // 6.2 查询宠物店账户
            account = this.petShopService.lambdaQuery()
                    .eq(PetShop::getId, id)
                    .one();
        } if (RoleEnum.ADMIN.name().equals(role)) {
            // 6.3 查询管理员账户
            account = this.adminService.lambdaQuery()
                    .eq(Admin::getId, id)
                    .one();
        }
        // 7.校验当前账户是否存在
        if (account == null) {
            throw new CustomException(ErrorCodeEnum.TOKEN_CHECK_ERROR);
        }
        // 8.通过用户的密码作为密钥再次验证token的合法性
        try {
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(account.getPassword())).build();
            // 验证token
            jwtVerifier.verify(token);
        } catch (Exception e) {
            throw  new CustomException(ErrorCodeEnum.TOKEN_CHECK_ERROR);
        }
        // 9.存放当前登录的账户至 threadLocal
        AccountUtils.setCurrentLoginAccount(account);
        // 10.放行
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        // 清除 threadLocal
        AccountUtils.remove();
    }
}
